﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.Server;
using PSE.Deployment.TeamFoundation.Entity.Enum;
using System.Threading;
using PSE.Deployment.TeamFoundation.Entity;

namespace PSE.Deployment.TeamFoundation.Communication
{
    public class EnvironmentBranch : CommunicationBase
    {
        #region Singleton
        private static EnvironmentBranch instance;
        protected EnvironmentBranch() 
        {
            Communication.VersionControl.Instance.TraceEvent += (sender, e) => RaiseEventTrace(e);
        }
        public static EnvironmentBranch Instance
        {
            get
            {
                if (instance == null)
                {
                    Mutex mutex = new Mutex();
                    mutex.WaitOne();

                    if (instance == null)
                        instance = new EnvironmentBranch();

                    mutex.Close();
                }
                return instance;
            }
        }
        #endregion Singleton

        public List<Entity.TeamProjectItem> GetItems(Entity.TeamProjectItem teamProjectItem)
        {
            if (teamProjectItem == null)
                throw new ArgumentNullException("teamProjectItem");

            RaiseEventTrace(string.Format("Obtendo os Itens do Branch do TeamProject {0}", teamProjectItem.Name));

            List<Entity.TeamProjectItem> items = new List<Entity.TeamProjectItem>();
            VersionControlServer versionControl = Communication.VersionControl.Instance.GetVersionControlServer();

            ItemSet tpItems = versionControl.GetItems(teamProjectItem.Path, RecursionType.OneLevel);

            TeamProjectItemType tpItemType = TeamProjectItemType.Any;

            foreach (Item item in tpItems.Items)
            {
                switch (item.ItemType)
                {
                    case ItemType.Any:
                        tpItemType = TeamProjectItemType.Any;
                        break;
                    case ItemType.File:
                        tpItemType = TeamProjectItemType.File;
                        break;
                    case ItemType.Folder:
                        tpItemType = TeamProjectItemType.Folder;
                        break;
                    default:
                        break;
                }

                if (item.ServerItem != teamProjectItem.Path)
                {
                    Entity.TeamProjectItem teamItem = new Entity.TeamProjectItem()
                    {
                        Name = item.ServerItem.Substring(item.ServerItem.LastIndexOf('/') + 1),
                        ItemType = tpItemType,
                        Path = item.ServerItem
                        //ContentLength = item.ItemType == ItemType.Folder && calculateForderSize ? CalculateForderSize(versionControl, item.ServerItem) : item.ContentLength
                    };
                    RaiseEventTrace(string.Format("Adicionando o Item {0} do tipo {1}", teamItem.Name, teamItem.ItemType.ToString()));
                    items.Add(teamItem);
                }
            }
            return items;
        }

        private long CalculateForderSize(VersionControlServer versionControl, string path)
        {
            if (versionControl == null)
                throw new ArgumentNullException("versionControl");

            if(string.IsNullOrEmpty(path))
                throw new ArgumentNullException("path");

            RaiseEventTrace("Calculando o tamanho da pasta");

            ItemSet items = versionControl.GetItems(path, RecursionType.Full);

            long size = items.Items.Sum(i => i.ContentLength);
            RaiseEventTrace(string.Format("Tamanho da Pasta: {0}", size));
            return size;
        }

        public List<Entity.EnvironmentBranch> GetBranches(Entity.TeamProject teamProject)
        {
            if (teamProject == null)
                throw new ArgumentNullException("teamProject");

            RaiseEventTrace(string.Format("Obtendo os Branchs do TeamProject {0}", teamProject.Name));

            List<Entity.EnvironmentBranch> branches = new List<Entity.EnvironmentBranch>();
            VersionControlServer versionControl = Communication.VersionControl.Instance.GetVersionControlServer();

            ItemSet tpItems = versionControl.GetItems(teamProject.ServerItem, RecursionType.OneLevel);

            foreach (Item item in tpItems.Items)
            {
                Uri uri = new Uri(item.ServerItem.Replace("$", "/"));

                if (uri.Segments.Count() >= 2)
                {
                    Entity.EnvironmentBranch branch = new Entity.EnvironmentBranch();
                    branch.Id = uri.Segments[1].ToString();
                    branch.SourceUri = item.ServerItem;

                    RaiseEventTrace(string.Format("Adicionando o Branch {0}", branch.Id));
                    branches.Add(branch);
                }
            }

            return branches;
        }

        public List<Entity.EnvironmentBranch> GetItems(Entity.TeamProject teamProject, ItemType itemType)
        {
            if (teamProject == null)
                throw new ArgumentNullException("teamProject");

            RaiseEventTrace(string.Format("Obtendo itens do tipo {0} de Branchs do TeamProject {1}", itemType.ToString(), teamProject.Name));

            List<Entity.EnvironmentBranch> branches = new List<Entity.EnvironmentBranch>();
            VersionControlServer versionControl = Communication.VersionControl.Instance.GetVersionControlServer();

            ItemSet tpItems = versionControl.GetItems(teamProject.ServerItem, RecursionType.OneLevel);

            foreach (Item item in tpItems.Items)
            {
                if (item.ItemType == itemType)
                {
                    Uri uri = new Uri(item.ServerItem.Replace("$", "/"));
                    Uri uriTeamProject = new Uri(teamProject.ServerItem.Replace("$", "/"));

                    if (uri.Segments.Count() > uriTeamProject.Segments.Count())
                    {
                        Entity.EnvironmentBranch branch = new Entity.EnvironmentBranch();
                        branch.Id = uri.Segments[uriTeamProject.Segments.Count()].ToString();
                        RaiseEventTrace(string.Format("Adicionando o Branch {0}", branch.Id));
                        branches.Add(branch);
                    }
                }
            }

            return branches;
        }
    }
}
